package com.example.demo.leetcode;

/**
 * ******************************************************
 *
 * @author liugh9
 * @version 1.0
 * @classname IntegerCoding
 * @description
 * @date 2023/08/14 20:03
 * <p>
 * ******************************************************
 */
public class IntegerCoding {

    /**
     * 1、正数的原码、反码、补码都一样；
     * 2、负数的反码 = 它的原码符号位不变，其他位取反（取反的意思：0 换成 1 、 1 换成 0 ）；
     * 3、负数的补码 = 它的反码 +1；
     * 4、0的反码、补码都是0；
     * 【特别注意】
     * 1、在计算机运算的时候，都是以 补码 的方式来运算的 。
     * 2、二进制 转为 十进制，必须使用 二进制 的原码进行转换 。
     */
    public static String integerCoding(String num) {
        // 题中提出提供的是非负整数
        int number = Integer.parseInt(num);
        // 整数对应二进制数
        // 由于正数的原码反码补码均一致，该结果即是补码
        StringBuilder str = new StringBuilder();
        while (number != 0) {
            str.insert(0, number % 2);
            number = number / 2;
        }

        // 1.编码时7位一组，每个字节的低7位用于存储待编码数字的补码
        // 2.字节的最高位表示后续是否还有字节，置1表示后面还有更多的字节，置0表示当前字节为最后一个字节。
        // 3.采用小端序编码，低位和低字节放在低地址 上。
        // 4.编码结果按16进制数的字符格式输出，小写字母需转换为大写字母
        int bit = str.length(); // 二进制数的位数
        // 分成几组
        int n = (bit + 6) / 7;
        // 凑成整数个7位
        int zero = 7 - (bit % 7 == 0 ? 7 : bit % 7);
        for (int i = 0; i < zero; i++) {
            str.insert(0, 0);
        }
        bit = 7 * n;
        StringBuilder result = new StringBuilder();
        for (int i = 1; i <= n; i++) {
            String hexadecimalNumber = encode(str, bit, i, i != n);
            result.append(hexadecimalNumber);
        }
        return result.toString();
    }

    private static String encode(StringBuilder str, int bit, int i, boolean residue) {
        // 15 0 1-7 8-14
        // 前面已经凑成了整数个7位，所以start不可能小于0
        int start = bit - i * 7;
        int end = bit - (i - 1) * 7;
        String item = "";
        // 还有高位未处理
        if (residue) {
            item = "1";
            item += str.substring(start, end);
        } else {
            // 已经是最高位
            item = "0";
            item += str.substring(start, end);
        }
        return toHexString(item).toUpperCase();
    }

    public static String toHexString(String binary) {
        StringBuilder hex = new StringBuilder();
        int iTmp;
        for (int i = 0; i < binary.length(); i += 4) {
            iTmp = 0;
            for (int j = 0; j < 4; j++) {
                iTmp += Integer.parseInt(binary.substring(i + j, i + j + 1)) << (4 - j - 1);
            }
            hex.append(Integer.toHexString(iTmp));
        }

        return hex.toString();
    }


    public static void main(String[] args) {
        System.out.println(integerCoding("100"));
    }

}
